home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / askrunlevel / runlevels.c < prev   
C/C++ Source or Header  |  1996-03-02  |  10KB  |  375 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <ctype.h>
  5. #include "../misc/misc.h"
  6. #include "askrunlevel.h"
  7. #include "internal.h"
  8. #include "../userconf/userconf.h"
  9. #include "../netconf/netconf.h"
  10. #include "../paths.h"
  11. #include "askrunlevel.m"
  12.  
  13. static HELP_FILE help_default (HELP_ASKRUN,"default");
  14. static HELP_FILE help_define (HELP_ASKRUN,"define");
  15.  
  16.  
  17. // Some keys for /etc/conf.linuxconf
  18. static const char ASKRUNLEVEL[]="askrunlevel";
  19. static const char TIMEOUT[]="timeout";
  20. static const char DEFMODE[]="defmode";
  21. static const char K_RUNLEVEL[]="runlevel";
  22.  
  23. #define NB_RUNLEVEL    6
  24. /*
  25.     Write the configuration parameter into /etc/askrunlevel.conf
  26. */
  27. static int askrunlevel_saveparm(ASK_PARM &parm)
  28. {
  29.     linuxconf_replace (ASKRUNLEVEL,TIMEOUT,parm.timeout);
  30.     linuxconf_replace (ASKRUNLEVEL,DEFMODE,parm.defmode);
  31.     return linuxconf_save();
  32. }
  33. /*
  34.     Write the configuration parameter into /etc/askrunlevel.conf
  35. */
  36. void askrunlevel_readparm(ASK_PARM &parm)
  37. {
  38.     parm.timeout = linuxconf_getvalnum(ASKRUNLEVEL,TIMEOUT,0);
  39.     parm.defmode = linuxconf_getvalnum(ASKRUNLEVEL,DEFMODE,4);
  40.     /* #Specification: askrunlevel / configuration file
  41.         askrunlevel stores its default operation mode into
  42.         /etc/conf.linuxconf. This file is optionnal. The
  43.         default setup is:
  44.  
  45.             runlevel 5, netlevel 0 -> text mode, no networking
  46.             No timeout (askrunlevel will wait forever)
  47.     */
  48. }
  49.  
  50. /*
  51.     parse one line of /etc/conf.linuxconf
  52. */
  53. PRIVATE void RUNLEVELS::parse (const char *str, RUNLEVEL *ptrun)
  54. {
  55.     /* #Specification: askrunlevel / runlevel definition / /etc/conf.linuxconf
  56.         The definitions of the different operation mode are
  57.         stored in /etc/conf.linuxconf with the following format
  58.  
  59.         #
  60.         askrunlevel.runlevel init net graphic_mode title ...
  61.         Where,
  62.  
  63.         init (runlevel for /sbin/init) is one of
  64.             1,2,3,4,5,6,S
  65.  
  66.         net is 0 1 or 2 for no network, client network and
  67.             server respectivly
  68.  
  69.         graphic is 0 1 or 2 for text mode, graphic mode (workstation)
  70.             and X terminal respectivly.
  71.         #
  72.  
  73.     */
  74.     str = str_skip(str);
  75.     ptrun->init_runlevel = *str++;
  76.     str = str_skip(str);
  77.     ptrun->netconf_runlevel = atoi(str++);
  78.     str = str_skip(str);
  79.     ptrun->graphic_level = atoi(str++);
  80.     ptrun->title.setfrom (str_skip(str));
  81. }
  82.  
  83. /*
  84.     Definition of the different runlevels available
  85. */
  86. PUBLIC RUNLEVELS::RUNLEVELS(
  87.     int graphic_ok,
  88.     int net_ok)
  89. {
  90.     static struct {
  91.         const char *mode;
  92.         const char *title;
  93.     }default_tbrun[]={
  94.         {"4 2 1",MSG_U(M_GR_NET,"Graphic & Network")},
  95.         {"4 0 1",MSG_U(M_GRONLY,"Graphic only")},
  96.         {"2 1 2",MSG_U(M_XTERMINAL,"X terminal")},
  97.         {"5 2 0",MSG_U(M_TX_NET,"Text mode & Network")},
  98.         {"3 0 0",MSG_U(M_TXONLY,"Text mode only")},
  99.         {"S 0 0",MSG_U(M_MAINTENANCE,"Maintenance mode")},
  100.     };
  101.     SSTRINGS lst;
  102.     /* #Specification: askrunlevel / operation mode / definition
  103.         The definition of the six different operation
  104.         mode are defined in /etc/conf.linuxconf
  105.     */
  106.     linuxconf_getall (ASKRUNLEVEL,K_RUNLEVEL,lst,0);
  107.     RUNLEVEL *ptrun = tbrun;
  108.     for (int i=0; i<NB_RUNLEVEL; i++, ptrun++){
  109.         if (i<lst.getnb()){
  110.             parse (lst.getitem(i)->get(),ptrun);
  111.         }else{
  112.             char buf[100];
  113.             sprintf (buf,"%s %s",default_tbrun[i].mode,default_tbrun[i].title);
  114.             parse (buf,ptrun);
  115.         }
  116.         ptrun->graphic_err = ptrun->graphic_level > 0
  117.             && !graphic_ok;
  118.         ptrun->net_err = ptrun->netconf_runlevel > 0 && !net_ok;
  119.         char buf[80];
  120.         ptrun->title.copy(buf);
  121.         if (ptrun->graphic_err || ptrun->net_err){
  122.             strcat (buf," ");
  123.             strcat (buf,MSG_U(M_NOTCONF,"(Not configured)"));
  124.         }
  125.         tbmenu[i].setfrom (buf);
  126.     }
  127. }
  128.  
  129. PUBLIC RUNLEVELS::~RUNLEVELS()
  130. {
  131. }
  132.  
  133. PUBLIC void RUNLEVELS::save()
  134. {
  135.     linuxconf_removeall (ASKRUNLEVEL,K_RUNLEVEL);
  136.     RUNLEVEL *ptrun = tbrun;
  137.     for (int i=0; i<NB_RUNLEVEL; i++, ptrun++){
  138.         char buf[80];
  139.         sprintf (buf,"%c %d %d %s"
  140.             ,ptrun->init_runlevel
  141.             ,ptrun->netconf_runlevel
  142.             ,ptrun->graphic_level
  143.             ,ptrun->title.get());
  144.         linuxconf_add (ASKRUNLEVEL,K_RUNLEVEL,buf);
  145.     }
  146.     linuxconf_save();
  147. }
  148.  
  149. PUBLIC void RUNLEVELS::setmenu (
  150.     const char *menuopt[])
  151. {
  152.     int ii=1;
  153.     for (unsigned i=0; i<sizeof(tbrun)/sizeof(tbrun[0]); i++, ii+=2){
  154.         menuopt[ii] = tbmenu[i].get();
  155.     }
  156. }
  157.  
  158. /*
  159.     Record the selected runlevels in the different files used later.
  160. */
  161. PUBLIC void RUNLEVELS::setlevel(int choice)
  162. {
  163.     /* #Specification: askrunlevel / talking to init / compatibitily
  164.         Most init expect to receive their new runlevel in
  165.         /etc/initrunlvl. Some do expect it in /var/run/initrunlvl.
  166.         I feel the later make more sens. Anyway, askrunlevel write
  167.         at both places.
  168.         
  169.         The askrunlevel utility was originally called by init
  170.         directly. It has been found that askrunlevel could be called
  171.         at the end of /etc/rc.d/rc.S (or whatever is on your system)
  172.         without any special support from init. The current askrunlevel
  173.         is playing is calling init to select the proper runlevel.
  174.     */
  175.     static char *tb[]={
  176.         VAR_RUN_INITRUNLEVEL,
  177.         ETC_INITRUNLEVEL
  178.     };
  179.     char levelstr[2];
  180.     levelstr[0] = tbrun[choice].init_runlevel;
  181.     levelstr[1] = '\0';
  182.     for (int i=0; i<2; i++){
  183.         FILE *fout = xconf_fopen (tb[i],"w");
  184.         if (fout != NULL){
  185.             fprintf (fout,"%s\n",levelstr);
  186.             fclose (fout);
  187.         }
  188.     }
  189.     netconf_setnetlevel (tbrun[choice].netconf_runlevel);
  190.     netconf_system_if ("telinit",levelstr);
  191. }
  192.  
  193.  
  194. /*
  195.     Let the user select the default runlevel for for next run
  196. */
  197. PUBLIC void RUNLEVELS::config()
  198. {
  199.     if (perm_rootaccess(MSG_U(P_BOOTMODE,"change the boot mode"))){
  200.         ASK_PARM parm;
  201.         askrunlevel_readparm (parm);
  202.         DIALOG dia;
  203.         dia.newf_title ("",MSG_U(T_DEFOPER,"Default operation mode"));
  204.         char choice = parm.defmode;
  205.         for (int i=0; i<5; i++){
  206.             dia.newf_radio ("",choice,i,tbmenu[i].get());
  207.         }
  208.         dia.newf_title ("","");
  209.         dia.newf_num (MSG_U(F_DELAY,"Delay to activate"),parm.timeout);
  210.         if (dia.edit (MSG_U(T_BOOTCMODE,"Boot mode configuration")
  211.             ,MSG_U(I_BOOTCMODE,"Select the default operation mode\n"
  212.              "and a timeout. A timeout of 0 means\n"
  213.              "to wait forever.\n")
  214.             ,help_default.getpath()
  215.             ,0)==MENU_ACCEPT){
  216.             parm.defmode = choice;
  217.             askrunlevel_saveparm (parm);
  218.             RUNLEVEL *ptrun = tbrun + choice;
  219.             if (ptrun->graphic_err || ptrun->net_err){
  220.                 xconf_notice(MSG_U(N_NOTCONF,"This runlevel is not yet"
  221.                     " configured"));
  222.             }
  223.         }
  224.     }
  225. }
  226.  
  227. /*
  228.     Initialise one combo box field
  229. */
  230. static void runlevels_setcombo (
  231.     DIALOG &dia,
  232.     const char *title,
  233.     SSTRING &s,
  234.     int curval,
  235.     const char *values[])
  236. {
  237.     s.setfrom (values[curval]);
  238.     FIELD_COMBO *comb = dia.newf_combo (title,s);
  239.     for (int i=0; values[i] != NULL; i++){
  240.         comb->addopt (values[i]);
  241.     }
  242. }
  243. /*
  244.     Get the index of a value in a table
  245. */
  246. static int runlevels_locate (
  247.     const char *values[],
  248.     SSTRING &s,
  249.     int ¬found,    // Will be set to id if not found
  250.             // Will be left unchanged if found.
  251.     int id)
  252. {
  253.     const char *pt = s.get();
  254.     int ret = 0;
  255.     int i;
  256.     for (i=0; values[i] != NULL; i++){
  257.         if (stricmp(values[i],pt)==0){
  258.             ret = i;
  259.             break;
  260.         }
  261.     }
  262.     if (values[i] == NULL) notfound = id;
  263.     return ret;
  264. }
  265.  
  266. PUBLIC void RUNLEVELS::define()
  267. {
  268.     /* #Specification: askrunlevel / runlevel definition
  269.         askrunlevel let the user select one of six operation
  270.         mode. It also let the user redefine (and rename)
  271.         those operation mode. The user can change any of
  272.         the six proposed mode.
  273.  
  274.         The name (title), the runlevel (for /sbin/init)
  275.         and the network mode (for netconf) and the graphic
  276.         mode (nographic, Workstation and X terminal) can
  277.         be selected for each mode.
  278.     */
  279.     DIALOG dia;
  280.     struct TBSTR{
  281.         SSTRING init;
  282.         SSTRING net;
  283.         SSTRING graphic;
  284.     }tbstr[NB_RUNLEVEL];
  285.     static const char *tbinit[] = {
  286.         "1","2","3","4","5","6",
  287.         "A","B","C","D","E","F",
  288.         "Maintenance",
  289.         NULL
  290.     };
  291.     static const char *tbnet[]={
  292.         MSG_U(M_NONET,"No network"),
  293.         MSG_U(M_CLIENT,"Client"),
  294.         MSG_U(M_SERVER,"Server"),
  295.         NULL
  296.     };
  297.     static const char *tbgraphic[]={
  298.         MSG_U(M_TEXTMODE,"Text mode"),
  299.         MSG_U(M_WORKSTATION,"Workstation"),
  300.         MSG_U(M_XTERM,"X terminal"),
  301.         NULL
  302.     };
  303.     RUNLEVEL *ptrun = tbrun;
  304.     TBSTR *ptstr = tbstr;
  305.     for (int i=0; i<NB_RUNLEVEL; i++, ptrun++, ptstr++){
  306.         dia.newf_title ("","");
  307.         dia.newf_str (MSG_U(F_TITLE,"Title"),ptrun->title);
  308.         int init_r = ptrun->init_runlevel;
  309.         if (init_r == 'S'){
  310.             init_r = 12;
  311.         }else if (isdigit(init_r)){
  312.             init_r -= '1';
  313.         }else{
  314.             init_r = (init_r - 'A') + 6;
  315.         }
  316.         runlevels_setcombo (dia,MSG_U(F_RUNLEVEL,"init runlevel")
  317.             ,ptstr->init
  318.             ,init_r
  319.             ,tbinit);
  320.         runlevels_setcombo (dia,MSG_U(F_NETMODE,"Network mode")
  321.             ,ptstr->net
  322.             ,ptrun->netconf_runlevel
  323.             ,tbnet);
  324.         runlevels_setcombo (dia,MSG_U(F_GRMODE,"Graphic mode")
  325.             ,ptstr->graphic
  326.             ,ptrun->graphic_level
  327.             ,tbgraphic);
  328.     }
  329.     int pos = 1;
  330.     while (1){
  331.         if (dia.edit (MSG_U(T_RUNDEF,"Runlevels definition")
  332.             ,MSG_U(I_RUNDEF,"You are allowed to name\n"
  333.              "the different runlevel for this machine\n")
  334.             ,help_define.getpath()
  335.             ,pos) != MENU_ACCEPT){
  336.             dia.restore();
  337.             break;
  338.         }else{
  339.             ptrun = tbrun;
  340.             ptstr = tbstr;
  341.             int notfound = 0;
  342.             for (int j=0; j<NB_RUNLEVEL; j++, ptrun++,ptstr++){
  343.                 int notfound_one = 0;
  344.                 int init_r = runlevels_locate (tbinit
  345.                     ,ptstr->init
  346.                     ,notfound_one,2);
  347.                 if (init_r == 12){
  348.                     init_r = 'S';
  349.                 }else if (init_r >= 6){
  350.                     init_r += 'A' - 6;
  351.                 }else{
  352.                     init_r += '1';
  353.                 }
  354.                 ptrun->init_runlevel = init_r;
  355.                 ptrun->netconf_runlevel = runlevels_locate (
  356.                     tbnet,ptstr->net,notfound_one,3);
  357.                 ptrun->graphic_level = runlevels_locate (
  358.                     tbgraphic,ptstr->graphic
  359.                     ,notfound_one,4);
  360.                 if (notfound_one){
  361.                     notfound = 1;
  362.                     xconf_error (MSG_U(E_IVLDEF,"Invalid definition"));
  363.                     pos = j * 5 + notfound_one;
  364.                     break;
  365.                 }
  366.             }
  367.             if (!notfound){
  368.                 save();
  369.                 break;
  370.             }
  371.         }
  372.     }
  373. }
  374.  
  375.